package com.xadrez.modelo;

import com.xadrez.exception.NumeroDeJogadorExcessoException;
import com.xadrez.exception.PecaProibidaException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Tabuleiro implements Cloneable {

    // VARIAVEIS ----------------------------------------------------------------------------------------------
    private String status;
    private Peca[][] quadrados;
    private Jogador jogadorUm;
    private Jogador jogadorDois;
    private Jogador jogadorDaVez;
    private int empate;

    public Tabuleiro(Jogador jogadorUm, Jogador jogadorDois) throws NumeroDeJogadorExcessoException {
        quadrados = new Peca[8][8];
        this.jogadorUm = jogadorUm;
        this.jogadorDois = jogadorDois;
//        jogadorDois = Jogador.getInstance("Jogador Humano 2");
        jogadorDaVez = jogadorUm;
        empate = 0;
    }

    public void desenha() {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                Peca peca = quadrados[i][j];
                if (peca != null) {
                    System.out.print("[" + peca.toString().substring(0, 2) + "_" + peca.getJogador().getNome().substring(0, 2) + "] ");
                } else {
                    System.out.print("[     ] ");
                }
            }
            System.out.println();
        }
        System.out.println("*******************");
    }

    // <editor-fold defaultstate="collapsed" desc="MÉTODOS DE BUSCA">
    //Verifica se existe adversário na posição x,y;
    public boolean temAdversarioNaPosicao(int x, int y) {
        boolean tem = false;

        if (x < 8 && y < 8 && x >= 0 && y >= 0) {
            if (quadrados[x][y] != null && quadrados[x][y].getJogador().equals(getJogadorAdversario())) {
                tem = true;
            }
        }
        return tem;
    }
    
    public boolean temReiAdversarioNaPosicao(int x, int y, Jogador jogador) {
        boolean tem = false;

        if (x < 8 && y < 8 && x >= 0 && y >= 0) {
            if (quadrados[x][y] != null && quadrados[x][y].getJogador().equals(getJogadorAdversario(jogador)) && (quadrados[x][y] instanceof Rei)) {
                tem = true;
            }
        }
        return tem;
    }
    
    public boolean temPecaDoJogadorNaPosicao(int x, int y, Jogador jogador) {
        boolean tem = false;

        if (x < 8 && y < 8 && x >= 0 && y >= 0) {
            if (quadrados[x][y] != null && quadrados[x][y].getJogador().equals(jogador)) {
                tem = true;
            }
        }
        return tem;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="MÉTODOS GETS e SETS">
    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Peca[][] getQuadrados() {
        return quadrados;
    }

    public void setQuadrados(Peca[][] quadrados) {
        this.quadrados = quadrados;
    }

    public Jogador getJogadorAdversario() {
        Jogador jogadorAdversario = jogadorUm;
        if (jogadorDaVez.equals(jogadorUm)) {
            jogadorAdversario = jogadorDois;
        }
        return jogadorAdversario;
    }
    
    public Jogador getJogadorAdversario(Jogador jogador) {
        Jogador jogadorAdv = jogadorUm;
        if (jogador.equals(jogadorUm)) {
            jogadorAdv = jogadorDois;
        }
        return jogadorAdv;
    }

    public Jogador getJogadorDaVez() {
        return jogadorDaVez;
    }

    public void setJogadorDaVez(Jogador jogadorDaVez) {
        this.jogadorDaVez = jogadorDaVez;
    }

    public Jogador getJogadorDois() {
        return jogadorDois;
    }

    public void setJogadorDois(Jogador jogadorDois) {
        this.jogadorDois = jogadorDois;
    }

    public Jogador getJogadorUm() {
        return jogadorUm;
    }

    public void setJogadorUm(Jogador jogadorUm) {
        this.jogadorUm = jogadorUm;
    }

    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="OUTROS MÉTODOS">
    @Override
    public Tabuleiro clone() {
        Tabuleiro aux = null;
        try {
            aux = (Tabuleiro) super.clone();
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(Tabuleiro.class.getName()).log(Level.SEVERE, null, ex);
        }
        aux.empate = empate;
        aux.jogadorDaVez = this.jogadorDaVez;
        aux.jogadorUm = this.jogadorUm;
        aux.jogadorDois = this.jogadorDois;
        aux.quadrados = new Peca[8][8];

        // Clonar tabuleiro
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (this.quadrados[i][j] != null) {
                    aux.quadrados[i][j] = (Peca) this.quadrados[i][j].clone();
                    aux.quadrados[i][j].setTabuleiro(aux);
                }
            }
        }

        return aux;
    }

    //Inicializa pecas nas primeiras e ultimas fileiras somente para o tabuleiro principal
    public void inicializaPecas() {
        //COLOCA PECAS DO JOGADOR 2
        quadrados[0][0] = new Torre(jogadorDois, this);
        quadrados[0][0].setPosicaoNoTabuleiro(new Posicao(0, 0));
        jogadorDois.getPecas().add(quadrados[0][0]);

        quadrados[0][1] = new Cavalo(jogadorDois, this);
        quadrados[0][1].setPosicaoNoTabuleiro(new Posicao(0, 1));
        jogadorDois.getPecas().add(quadrados[0][1]);

        quadrados[0][2] = new Bispo(jogadorDois, this);
        quadrados[0][2].setPosicaoNoTabuleiro(new Posicao(0, 2));
        jogadorDois.getPecas().add(quadrados[0][2]);

        quadrados[0][3] = new Rainha(jogadorDois, this);
        quadrados[0][3].setPosicaoNoTabuleiro(new Posicao(0, 3));
        jogadorDois.getPecas().add(quadrados[0][3]);

        quadrados[0][4] = new Rei(jogadorDois, this);
        quadrados[0][4].setPosicaoNoTabuleiro(new Posicao(0, 4));
        jogadorDois.getPecas().add(quadrados[0][4]);

        quadrados[0][5] = new Bispo(jogadorDois, this);
        quadrados[0][5].setPosicaoNoTabuleiro(new Posicao(0, 5));
        jogadorDois.getPecas().add(quadrados[0][5]);

        quadrados[0][6] = new Cavalo(jogadorDois, this);
        quadrados[0][6].setPosicaoNoTabuleiro(new Posicao(0, 6));
        jogadorDois.getPecas().add(quadrados[0][6]);

        quadrados[0][7] = new Torre(jogadorDois, this);
        quadrados[0][7].setPosicaoNoTabuleiro(new Posicao(0, 7));
        jogadorDois.getPecas().add(quadrados[0][7]);

        quadrados[1][0] = new Peao(jogadorDois, this);
        quadrados[1][0].setPosicaoNoTabuleiro(new Posicao(1, 0));
        jogadorDois.getPecas().add(quadrados[1][0]);

        quadrados[1][1] = new Peao(jogadorDois, this);
        quadrados[1][1].setPosicaoNoTabuleiro(new Posicao(1, 1));
        jogadorDois.getPecas().add(quadrados[1][1]);

        quadrados[1][2] = new Peao(jogadorDois, this);
        quadrados[1][2].setPosicaoNoTabuleiro(new Posicao(1, 2));
        jogadorDois.getPecas().add(quadrados[1][2]);

        quadrados[1][3] = new Peao(jogadorDois, this);
        quadrados[1][3].setPosicaoNoTabuleiro(new Posicao(1, 3));
        jogadorDois.getPecas().add(quadrados[1][3]);

        quadrados[1][4] = new Peao(jogadorDois, this);
        quadrados[1][4].setPosicaoNoTabuleiro(new Posicao(1, 4));
        jogadorDois.getPecas().add(quadrados[1][4]);

        quadrados[1][5] = new Peao(jogadorDois, this);
        quadrados[1][5].setPosicaoNoTabuleiro(new Posicao(1, 5));
        jogadorDois.getPecas().add(quadrados[1][5]);

        quadrados[1][6] = new Peao(jogadorDois, this);
        quadrados[1][6].setPosicaoNoTabuleiro(new Posicao(1, 6));
        jogadorDois.getPecas().add(quadrados[1][6]);

        quadrados[1][7] = new Peao(jogadorDois, this);
        quadrados[1][7].setPosicaoNoTabuleiro(new Posicao(1, 7));
        jogadorDois.getPecas().add(quadrados[1][7]);

        //COLOCA PECAS DO JOGADOR 1
        quadrados[6][0] = new Peao(jogadorUm, this);
        quadrados[6][0].setPosicaoNoTabuleiro(new Posicao(6, 0));
        jogadorUm.getPecas().add(quadrados[6][0]);

        quadrados[6][1] = new Peao(jogadorUm, this);
        quadrados[6][1].setPosicaoNoTabuleiro(new Posicao(6, 1));
        jogadorUm.getPecas().add(quadrados[6][1]);

        quadrados[6][2] = new Peao(jogadorUm, this);
        quadrados[6][2].setPosicaoNoTabuleiro(new Posicao(6, 2));
        jogadorUm.getPecas().add(quadrados[6][2]);

        quadrados[6][3] = new Peao(jogadorUm, this);
        quadrados[6][3].setPosicaoNoTabuleiro(new Posicao(6, 3));
        jogadorUm.getPecas().add(quadrados[6][3]);

        quadrados[6][4] = new Peao(jogadorUm, this);
        quadrados[6][4].setPosicaoNoTabuleiro(new Posicao(6, 4));
        jogadorUm.getPecas().add(quadrados[6][4]);

        quadrados[6][5] = new Peao(jogadorUm, this);
        quadrados[6][5].setPosicaoNoTabuleiro(new Posicao(6, 5));
        jogadorUm.getPecas().add(quadrados[6][5]);

        quadrados[6][6] = new Peao(jogadorUm, this);
        quadrados[6][6].setPosicaoNoTabuleiro(new Posicao(6, 6));
        jogadorUm.getPecas().add(quadrados[6][6]);

        quadrados[6][7] = new Peao(jogadorUm, this);
        quadrados[6][7].setPosicaoNoTabuleiro(new Posicao(6, 7));
        jogadorUm.getPecas().add(quadrados[6][7]);

        quadrados[7][0] = new Torre(jogadorUm, this);
        quadrados[7][0].setPosicaoNoTabuleiro(new Posicao(7, 0));
        jogadorUm.getPecas().add(quadrados[7][0]);

        quadrados[7][1] = new Cavalo(jogadorUm, this);
        quadrados[7][1].setPosicaoNoTabuleiro(new Posicao(7, 1));
        jogadorUm.getPecas().add(quadrados[7][1]);

        quadrados[7][2] = new Bispo(jogadorUm, this);
        quadrados[7][2].setPosicaoNoTabuleiro(new Posicao(7, 2));
        jogadorUm.getPecas().add(quadrados[7][2]);

        quadrados[7][3] = new Rainha(jogadorUm, this);
        quadrados[7][3].setPosicaoNoTabuleiro(new Posicao(7, 3));
        jogadorUm.getPecas().add(quadrados[7][3]);

        quadrados[7][4] = new Rei(jogadorUm, this);
        quadrados[7][4].setPosicaoNoTabuleiro(new Posicao(7, 4));
        jogadorUm.getPecas().add(quadrados[7][4]);

        quadrados[7][5] = new Bispo(jogadorUm, this);
        quadrados[7][5].setPosicaoNoTabuleiro(new Posicao(7, 5));
        jogadorUm.getPecas().add(quadrados[7][5]);

        quadrados[7][6] = new Cavalo(jogadorUm, this);
        quadrados[7][6].setPosicaoNoTabuleiro(new Posicao(7, 6));
        jogadorUm.getPecas().add(quadrados[7][6]);

        quadrados[7][7] = new Torre(jogadorUm, this);
        quadrados[7][7].setPosicaoNoTabuleiro(new Posicao(7, 7));
        jogadorUm.getPecas().add(quadrados[7][7]);
    }
  
    public void plusEmpate() {
        empate++;
    }

    public void zeraEmpate() {
        this.empate = 0;
    }

    public boolean empate() {
        if (empate >= 50) {
            return true;
        } else {
            return false;
        }
    }

    public Peca promocao(Peca pecaAntiga, Class c) throws PecaProibidaException, InstantiationException, IllegalAccessException {

        Peca pecaNova = (Peca) c.newInstance();
        if ((pecaNova instanceof Peao) || (pecaNova instanceof Rei)) {
            throw new PecaProibidaException("Você não pode evoluir para peão ou um Rei");
        }
        pecaNova.setAtiva(pecaAntiga.isAtiva());
        pecaNova.setJogador(pecaAntiga.getJogador());
        pecaNova.setPosicaoNoTabuleiro(pecaAntiga.getPosicaoNoTabuleiro());
        pecaNova.setTabuleiro(pecaAntiga.getTabuleiro());
        getQuadrados()[pecaAntiga.getPosicaoNoTabuleiro().getX()][pecaAntiga.getPosicaoNoTabuleiro().getY()] = pecaNova;

        if (pecaNova.getJogador().getId() == 1) {
            jogadorUm.getPecas().remove(pecaAntiga);
            jogadorUm.getPecas().add(pecaNova);
        } else {
            jogadorDois.getPecas().remove(pecaAntiga);
            jogadorDois.getPecas().add(pecaNova);
        }
        return pecaNova;
    }
    // </editor-fold>
}
